package cn.wenhaha.app.mapping.service.imp;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.wenhaha.app.job.kit.ConfigKit;
import cn.wenhaha.app.job.kit.MappingKit;
import cn.wenhaha.app.job.service.JobControlService;
import cn.wenhaha.app.mapping.bean.dto.Condition;
import cn.wenhaha.app.mapping.bean.dto.ConfigContext;
import cn.wenhaha.app.mapping.bean.dto.MappingObj;
import cn.wenhaha.app.mapping.bean.dto.SyncObjectContext;
import cn.wenhaha.app.mapping.bean.vo.MappingListVO;
import cn.wenhaha.app.mapping.bean.vo.MappingVo;
import cn.wenhaha.app.mapping.manager.MappingManager;
import cn.wenhaha.app.mapping.service.MappingService;
import cn.wenhaha.common.bean.entity.Switch;
import cn.wenhaha.common.bean.query.mapping.ListQuery;
import cn.wenhaha.common.db.bean.SysMapping;
import cn.wenhaha.common.exception.ApiMSGException;
import cn.wenhaha.common.utils.PageConvert;
import com.jfinal.plugin.activerecord.Page;
import org.quartz.Trigger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

/**
 * --------
 *
 * @author ：wyndem
 * @Date ：Created in 2022-09-19 21:34
 */
@Service
public class MappingServiceImp implements MappingService {

    @Resource
    private SysMapping sysMapping;
    @Resource
    private MappingManager mappingManager;
    @Resource
    private JobControlService jobControlService;

    @Override
    public Integer save(SyncObjectContext context) {
        boolean update = StrUtil.isNotEmpty(context.getId());

        SysMapping sysMapping = builderModel(context);
        String createBy = StpUtil.getLoginId().toString();

        List<MappingObj> source1 = context.getMapping().getSource1();
        List<MappingObj> source2 = context.getMapping().getSource2();

        Condition condition = context.getConfig().getCondition();

        // 双方必须有主键
        MappingObj keyFileName = MappingKit.getKeyFileName(source1);
        MappingObj keyFileName1 = MappingKit.getKeyFileName(source2);

        // 检查 双方是否写了映射
        boolean s1 = MappingKit.checkMappingValue(source1);
        boolean s2 = MappingKit.checkMappingValue(source2);
        // 检查id之前必须要有关联关系
        if (s1 && !MappingKit.isTargetValue(keyFileName)) {
            throw new ApiMSGException(-1, context.getSource1ObjApi() + "主键" + keyFileName.getNameApi() + "末对应对方主键");
        }
        if (s2 && !MappingKit.isTargetValue(keyFileName1)) {
            throw new ApiMSGException(-1, context.getSource2ObjApi() + "主键" + keyFileName1.getNameApi() + "末对应对方主键");
        }

        // 如果设置了映射，则必须要写同步条件
        if (s1 && !ConfigKit.isConditionValue(condition.getSource1())) {
            throw new ApiMSGException(-1, context.getSource1ObjApi() + "对象，检查同步条件为必填");
        }
        if (s2 && !ConfigKit.isConditionValue(condition.getSource2())) {
            throw new ApiMSGException(-1, context.getSource2ObjApi() + "对象，检查同步条件为必填");
        }


        if (update) {
            sysMapping.setUpdateBy(createBy);
            sysMapping.update();
        } else {
            sysMapping.setCreateBy(createBy);
            sysMapping.save();
        }
        return Integer.parseInt(sysMapping.getId());
    }


    private SysMapping builderModel(SyncObjectContext context) {
        SysMapping sysMapping = new SysMapping();
        boolean update = StrUtil.isNotEmpty(context.getId());
        if (!update) {
            int exist = sysMapping.findByNameNumber(context.getName());
            if (exist > 0) {
                throw ApiMSGException.build(6101);
            }
            sysMapping.setCreateTime(DateUtil.now());
        }
        if (update) {
            sysMapping.setId(context.getId());
            sysMapping.setUpdateTime(DateUtil.now());
        }
        sysMapping.setName(context.getName());
        sysMapping.setCron(context.getCron());


        sysMapping.setSource1Obj(context.getSource1ObjApi());
        sysMapping.setSource2Obj(context.getSource2ObjApi());

        sysMapping.setSource1Code(context.getSource1());
        sysMapping.setSyncCore1(context.getSyncCore1());

        sysMapping.setSource2Code(context.getSource2());
        sysMapping.setSyncCore2(context.getSyncCore2());

        sysMapping.setSource1Id(context.getSource1Id());
        sysMapping.setSource2Id(context.getSource2Id());
        sysMapping.setSource1Name(context.getSource1Name());
        sysMapping.setSource2Name(context.getSource2Name());

        sysMapping.setConfig(JSONUtil.toJsonStr(context.getConfig()));
        sysMapping.setMapping(JSONUtil.toJsonStr(context.getMapping()));
        sysMapping.setStatus(Switch.OFF.getCode());
        sysMapping.setTest(Switch.OFF.getCode());

        return sysMapping;

    }

    @Override
    public Page<MappingListVO> list(ListQuery query) {
        query.setCreateId(StpUtil.getLoginId().toString());
        Page<SysMapping> sysMappingPage = sysMapping.queryPageList(query);
        return PageConvert.convertPage(sysMappingPage, model -> new MappingListVO()
                .setId(model.getId())
                .setName(model.getName())
                .setCron(model.getCron())
                .setTest(Switch.ON.getCode().equals(model.getTest()))
                .setStatus(model.getStatus().toString())
                .setObj1APi(model.getSource1Obj())
                .setObj2APi(model.getSource2Obj())
                .setSource1Name(model.getSource1Name())
                .setSource2Name(model.getSource2Name())
                .setCreateTime(model.getCreateTime())
                .setUpdateTime(model.getUpdateTime())
                .setSynCore1(model.getSyncCore1())
                .setSynCore2(model.getSyncCore2()));
    }

    @Override
    public MappingVo detail(String id) {
        return mappingManager.detail(id);
    }

    @Override
    public void remove(Integer id) {
        SysMapping sysMapping = Optional.ofNullable(this.sysMapping.findById(id))
                .orElseThrow(() -> ApiMSGException.build(6102));
        if (Switch.ON.getCode().equals(sysMapping.getStatus())) {
            throw ApiMSGException.build(6103);
        }
        sysMapping.delete();
    }

    @Override
    public void saveConfig(String id, ConfigContext context) {
        SysMapping sysMapping = Optional.ofNullable(this.sysMapping.findById(id))
                .orElseThrow(() -> ApiMSGException.build(6102));

        sysMapping.setCron(context.getCron());
        sysMapping.setConfig(JSONUtil.toJsonStr(context));
        sysMapping.update();

        if (Switch.ON.getCode().equals(sysMapping.getStatus())) {
            jobControlService.close(id,sysMapping.getCreateBy());
            jobControlService.start(sysMapping);
        }
    }

    @Override
    public void switchMapping(String id) {
        SysMapping sysMapping = Optional.ofNullable(this.sysMapping.findById(id))
                .orElseThrow(() -> ApiMSGException.build(6102));
        // 当前映射没有进行测试
        if (Switch.OFF.getCode().equals(sysMapping.getTest()) && Switch.OFF.getCode().equals(sysMapping.getStatus())) {
            throw ApiMSGException.build(9001);
        }
        boolean result;
        // 进行关闭
        if (Switch.ON.getCode().equals(sysMapping.getStatus())) {
            result = jobControlService.close(sysMapping.getId(), sysMapping.getCreateBy());
            sysMapping.setStatus(Switch.OFF.getCode());
        } else {
            result = jobControlService.start(sysMapping);
            sysMapping.setStatus(Switch.ON.getCode());
        }

        if (result) {
            sysMapping.update();
        }

    }


    @Override
    public void test(String id) {
        SysMapping sysMapping = Optional.ofNullable(this.sysMapping.findById(id))
                .orElseThrow(() -> ApiMSGException.build(6102));
        jobControlService.testRun(sysMapping);

    }


    @Override
    public void testOk(String id) {
        SysMapping sysMapping = Optional.ofNullable(this.sysMapping.findById(id))
                .orElseThrow(() -> ApiMSGException.build(6102));

        sysMapping.setTest(Switch.ON.getCode());
        sysMapping.update();
    }
}
